

#ifndef _MATRIX
#  define _MATRIX

#  include <vector.h>
#  include <config.h>
#  include <stdio.h>

typedef struct vm_matrix {

  double **data;

  int rows;
  int columns;

} vm_matrix;


typedef struct vm_matrix_rc {

  double *data;
  int elems;

} vm_matrix_rc;

typedef struct vm_matrix_rc vm_matrix_row;
typedef struct vm_matrix_rc vm_matrix_col;

#  define VM_ROW  1
#  define VM_COL  2

vm_matrix *vm_read_matrix(char *);
void       vm_get_matrix_row(vm_matrix *, int, vm_matrix_row *);
void       vm_get_matrix_col(vm_matrix *, int, vm_matrix_col *);

char       vm_matrix_dot(vm_matrix_rc *, vm_matrix_rc *, double *);
vm_matrix *vm_matrix_add(vm_matrix *, vm_matrix *);
vm_matrix *vm_matrix_sub(vm_matrix *, vm_matrix *);
vm_matrix *vm_matrix_mult(vm_matrix *, vm_matrix *);
vm_matrix *vm_transpose(vm_matrix *);
vm_matrix *vm_inverse(vm_matrix *);
int        vm_determinant(vm_matrix *, double *);
int        vm_swap_rows(vm_matrix *, int, int);

vm_matrix *vm_minor_matrix(vm_matrix *, int, int);
double     vm_cofactor(vm_matrix *, int, int);
vm_matrix *vm_adjoint(vm_matrix *);

vm_matrix *vm_gaussian_elim(vm_matrix *);
vm_matrix *vm_row_echelon_form(vm_matrix *);
vm_matrix *vm_rref(vm_matrix *);

vm_matrix *vm_vector_to_matrix(vm_vector *);
void       vm_matrix_to_vector(vm_matrix *, vm_vector *);
vm_matrix *vm_make_matrix(int, int);
void       vm_free_matrix(vm_matrix *);
void       vm_free_only_matrix(vm_matrix *);
void       vm_fprint_matrix(FILE *, vm_matrix *, char *);
void       vm_print_matrix(vm_matrix *, char *);
void       vm_print_matrix_rc(vm_matrix_rc *);
void       vm_fprint_cr_matrix(FILE *, vm_matrix *);
void       vm_print_cr_matrix(vm_matrix *);
void       vm_fprint_octave_matrix(FILE *, vm_matrix *);

#endif
